const cloud = require('wx-server-sdk');
const crypto = require('crypto');
const axios = require('axios');

cloud.init({
  env: cloud.DYNAMIC_CURRENT_ENV,
});

const db = cloud.database();

/**
 * 打印服务
 * @async
 * @function printTicket
 * @param {Object} request - 请求对象
 * @param {string} request.orderId - 订单ID
 * @param {number} [request.times=1] - 打印次数
 * @returns {Promise<Object>} 返回处理结果
 * @throws {Error} 当打印失败时抛出错误
 * @description 
 * 1. 查询订单信息
 * 2. 获取学校信息和打印机配置
 * 3. 生成打印内容
 * 4. 调用飞鹅云打印接口
 */
async function printTicket(request) {
  
  const { times = 1, orderId } = request;

  // 固定的飞鹅云配置信息
  const config = {
    user: '17671311571@163.com',
    ukey: 'MRf53hI9wT9rpGs4',
    apiUrl: 'https://api.feieyun.cn/Api/Open/',
  };

  if (!orderId) {
    return { ret: -1, msg: '缺少订单信息，无法打印' };
  }

  try {
    // 查询订单信息
    let orderInfo = await queryOrderInfo(orderId);
    if (!orderInfo) return { ret: -1, msg: '未找到对应的订单信息' };

    // 根据学校名称获取缩写
    let schoolInfo = await getSchoolInfo(orderInfo.address.school);
    orderInfo.address.schoolAbbr = schoolInfo.address_name_abbr;

    // 获取订单类型描述
    orderInfo.orderTypeDesc = await getOrderTypeDesc(orderInfo);

    // 查询打印机编号列表
    const snList = await getPrinterSnList(schoolInfo.address_code, orderInfo.orderItem.productId);

    if (!snList || snList.length === 0) {
      return { ret: -1, msg: '未找到匹配的打印机编号列表' };
    }

    // 生成打印内容
    const content = generatePrintContent(orderInfo);

    // 循环调用打印接口
    const results = [];
    for (const sn of snList) {
      try {
        const result = await sendPrintRequest({ ...config, sn }, content, times);
        results.push({ sn, success: true, result });
      } catch (error) {
        console.error(`打印失败，打印机编号: ${sn}`, error);
        console.error('Stack:', error.stack || '无堆栈信息');
        results.push({ sn, success: false, error: error.message });
      }
    }

    return {
      ret: 0,
      msg: '打印完成',
      data: results,
    };   
  } catch (err) {
    console.error("打印服务错误:", err.message);
    console.error("Stack:", err.stack || '无堆栈信息');
    return { ret: -1, msg: err.message };
  }
}

/**
 * 根据学校和产品类型查询打印机配置
 */
async function getPrinterSnList(schoolCode, productId) {
  try {
    const result = await db.collection('config')
      .where({
        config_name: "printTicketConfig",
        school_code: schoolCode,
        product_id: productId,
      })
      .get();

    if (result.data.length > 0) {
      return result.data[0].content.sn;
    }
    return null;
  } catch (error) {
    console.error('查询打印机编号失败:', error.message);
    console.error('Stack:', error.stack || '无堆栈信息');
    throw new Error('查询打印机编号失败，请检查数据库连接');
  }
}

/**
 * 格式化时间为 YYYY-MM-DD HH:mm:ss
 */
function formatDateToYY_MM_DD_HH_MM_SS(date) {
  const year = date.getFullYear();
  const month = String(date.getMonth() + 1).padStart(2, '0');
  const day = String(date.getDate()).padStart(2, '0');
  const hours = String(date.getHours()).padStart(2, '0');
  const minutes = String(date.getMinutes()).padStart(2, '0');
  const seconds = String(date.getSeconds()).padStart(2, '0');
  return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
}

/**
 * 将对象的键从下划线命名转换为驼峰命名
 */
function toCamelCase(data) {
  if (Array.isArray(data)) {
    return data.map((item) => toCamelCase(item));
  }
  if (data && typeof data === 'object') {
    return Object.keys(data).reduce((result, key) => {
      const camelKey = key.replace(/_([a-z])/g, (_, letter) => letter.toUpperCase());
      result[camelKey] = toCamelCase(data[key]);
      return result;
    }, {});
  }
  return data;
}

/**
 * 根据订单类型获取描述
 */
async function getOrderTypeDesc(orderFinalInfo) {
  const productId = orderFinalInfo.orderItem?.productId;
  const typeMap = {
    PWashShoes: '洗鞋',
    PPacakgePickUp: '代取',
    PWashClothes: '洗衣',
    PPrintBlackAndWhite: '打印',
    PPaoTui: '跑腿',
  };
  return typeMap[productId] || '-';
}

/**
 * 根据学校名字获取学校缩写
 */
async function getSchoolInfo(addressName) {
  if (!addressName) return addressName;

  try {
    const res = await db.collection('config').where({ config_name: 'school_list' }).get();
    if (res.data.length === 0) return addressName;

    const content = res.data[0].content || [];
    const target = content.find((item) => item.address_name === addressName || item.address_code === addressName);

    return target;
  } catch (error) {
    console.error('获取学校信息失败:', error.message);
    console.error('Stack:', error.stack || '无堆栈信息');
    return addressName;
  }
}

/**
 * 查询订单信息
 */
async function queryOrderInfo(orderId) {
  try {
    const result = await db.collection('order').where({ order_id: orderId }).get();
    if (result.data && result.data.length > 0) {
      const order = result.data[0];

      ['create_ts', 'update_ts', 'complaint_info.camplaint_time'].forEach((key) => {
        if (key in order) {
          const keys = key.split('.');
          const field = keys.reduce((obj, k) => obj?.[k], order);
          if (field) keys.reduce((obj, k, i) => (i === keys.length - 1 ? (obj[k] = formatDateToYY_MM_DD_HH_MM_SS(new Date(field))) : obj[k]), order);
        }
      });

      return toCamelCase(order);
    }
    return null;
  } catch (err) {
    console.error('订单查询失败:', err.message);
    console.error('Stack:', err.stack || '无堆栈信息');
    throw new Error('订单查询失败，请检查数据库连接');
  }
}

/**
 * 生成打印内容
 */
function generatePrintContent(orderInfo) {
  return `
    <TEXT x="30" y="20" font="12" w="1" h="1" r="0">${orderInfo.address.phone} ${orderInfo.address.name}</TEXT>
    <TEXT x="30" y="55" font="12" w="1" h="1" r="0">${orderInfo.address.schoolAbbr} ${orderInfo.address.detail} ${orderInfo.orderTypeDesc}</TEXT>
    <TEXT x="30" y="90" font="12" w="1" h="1" r="0">${orderInfo.deliverTime}</TEXT>
    <BC128 x="40" y="125" h="80" s="1" r="0" n="2" w="4">${orderInfo.orderId}</BC128>
  `;
}

/**
 * 发送打印请求
 */
async function sendPrintRequest(config, content, times) {
  const stime = Math.floor(Date.now() / 1000);
  const sig = crypto.createHash('sha1').update(config.user + config.ukey + stime).digest('hex');
  const params = new URLSearchParams({
    user: config.user,
    stime,
    sig,
    apiname: 'Open_printLabelMsg',
    sn: config.sn,
    content,
    times,
  });

  try {
    const response = await axios.post(config.apiUrl, params, {
      headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
    });

    if (response.data.ret !== 0) {
      console.error('打印失败，飞鹅云返回信息:', response.data);
      throw new Error(response.data.msg || '打印失败');
    }

    return response.data;
  } catch (err) {
    console.error('打印请求失败:', err.message);
    console.error('Stack:', err.stack || '无堆栈信息');
    throw new Error('打印请求失败，请检查网络或参数');
  }
}

module.exports = {
  printTicket: printTicket
};
